package insight.springia5.chapter07.jms.producer;

import insight.springia5.chapter06.domain.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;


/**
 * 使用 JmsTemplate 发送消息
 * 
 * 有三类方法
 * 1. send 需要消息构造器 MessageCreator
 * 2. convertAndSend 直接接受对象
 * 3. convertAndSend 带有后期处理消息 MessagePostProcessor
 * 
 * 3种重载
 * 1. 不带目的地
 * 2. 使用 Destination 对象
 * 3. 使用 String 指明地点
 *
 * @author insight
 * @since 2021/7/21
 */
@Service
public class OrderMessageProducerImpl implements OrderMessageProducer {
    private JmsTemplate jmsTemplate;
    private Destination destination;

    @Autowired
    public OrderMessageProducerImpl(JmsTemplate jmsTemplate,
                                    Destination destination) {
        this.jmsTemplate = jmsTemplate;
        this.destination = destination;
    }

    /**
     * 最简单的 send()
     * 在配置中指明默认地点
     */
    /*@Override
    public void sendOrder(Order order) {
        jmsTemplate.send(session ->
                session.createObjectMessage(order)
        );
    }*/

    /**
     * 使用 Destination 对象
     */
    /*@Override
    public void sendOrder(Order order) {
        jmsTemplate.send(
                destination,
                session -> session.createObjectMessage(order)
        );
    }*/

    /**
     * Destination 对象可以设置属性 但实际情况中 几乎不会设置
     * 因此可以直接指定地点即可
     */
    /*@Override
    public void sendOrder(Order order) {
        jmsTemplate.send(
                "tacocloud.order.queue",
                session -> session.createObjectMessage(order)
        );
    }*/

    /**
     * 后期处理消息
     * 很遗憾 send() 无法访问底层的消息
     */
    /*@Override
    public void sendOrder(Order order) {
        jmsTemplate.send(
                "tacocloud.order.queue",
                session -> {
                    Message message = session.createObjectMessage(order);
                    message.setStringProperty();
                }
        );
    }*/

    /**
     * convertAndSend() 需要一个 MessageConverter 来帮你转换成消息
     *
     * 最简单的有 SimpleMessageConverter 但需要对象序列化 (虽然 Order 序列化了)
     * 也可使用 MappingJackson2MessageConverter
     */
    /*@Override
    public void sendOrder(Order order) {
        jmsTemplate.convertAndSend(order);
    }*/

    /**
     * 需要添加订单来源 一个方法时修改 Order 类
     * 更简单的方法是 在消息头部添加来源
     */
    /*@Override
    public void sendOrder(Order order) {
        jmsTemplate.convertAndSend(order,
                message -> {
                    message.setStringProperty("ORDER_SOURCE", "WEB");
                    return message;
                }
        );
    }*/

    /**
     * 消息转换器存在复用 可以抽取
     */
    @Override
    public void sendOrder(Order order) {
        jmsTemplate.convertAndSend(order,
                this::addOrderWebSource
        );
    }

    private Message addOrderWebSource(Message message) throws JMSException {
        message.setStringProperty("ORDER_SOURCE", "WEB");
        return message;
    }

    /*@Scheduled(cron = "0/2 * * * * ?")
    public void scheduledPublish() {
        jmsTemplate.convertAndSend("tacocloud.test.queue", 
                "定时消息" + System.currentTimeMillis());
    }*/
}